字符串操作
bash支持很多关于字符串的操作,不过可惜的是,这些操作缺乏统一性,有一些是使用参数等,另外一些是通过内建命令expr
命令来实现,这会导致不同的语法功能的重叠,会比较混乱,下面简单介绍一下使用参数和命令的实现字符串的操作。
字符串长度(String Length)
$(#string) 这里是和C语言中的strlen()是相同的。
expr length $string 同样表示string串的长度。
1
2
3
4
5
6
7
string=abcdefgHIGKL
#使用第一种方法$(#string)
echo "string的长度是:${#string}"
#使用第二种方法使用expr内建命令 优点简单易懂
echo "string的长度是:`expr length $string`"
`
字符串从开头匹配子字串的长度
方法如下:
1
2
3stringZ=abcABC123ABCab
echo `expr match "$stringZ" 'abc[A-Z]*.2'`
echo `expr $stringZ : 'abc[A-Z]*.2'`匹配到子串的位置 (index)
1
echo `expr index $stringZ 'abc[A-Z]*.2'`
子字符串的截取
${string:position} 从positon位置截取字符串string。
${string:positong:length} 从positon位置截取字符串string,并且限定截取长度为length。
expr substr $string $positon $length 意思同上。
expr match $string ‘\(substring \)’ 这里的substring是正则表达式。
1
2
3
4
5#截取字符串
echo ${stringZ:5}
echo ${stringZ:5:4}
echo `expr substr $stringZ 5 4`
echo `expr match $stringZ '\(abc[A-Z]*.2\)'`
从字符串中移除子字符串
${string#substring} substring是子字符串。并且需要注意的是:该方法表示的是向后移除该子字符串最短匹配到的字符串。
${string##substring} 与上面的正好相反。该方法表示的是向后移除该字符串最长匹配到的字符串。
${string%substring} 该方法表示的是由后向前移除该子字符串最短匹配到的字符串。
${string%%substring} 该方法表示的是由后向前移除该字符串最长匹配到的字符串。
1
2
3
4
5
6
7
8
9
10echo "移除字符串"
echo ${stringZ#a*b}
echo ${stringZ##a*b}
echo ${stringZ%a*c}
echo ${stringZ%%a*c}
#结果:
#ABC123ABCabc
#c
#abcABC123ABC
#
子字符串替换
${string/substring/replacement} 替换第一个匹配到substring的字符串,替换为replacement。
${string//substring/replacement} 替换所有匹配到的字符。
${string/#substring/replacement} 替换由前向后匹配到的字符。
${string/%substring/replacement} 替换由后向前匹配到的字符。
1
2
3
4
5
6
7
8
9
10echo "---------字符串替换---------"
echo ${stringZ/abc/xyz}
echo ${stringZ//abc/xyz}
echo ${stringZ/#abc/xyz}
echo ${stringZ/%abc/xyz}
#结果:
#xyzABC123ABCabc
#xyzABC123ABCxyz
#xyzABC123ABCabc
#abcABC123ABCxyz
使用awk操作字符串
现学先卖,三十分钟学会AWK,快速了解和应用awk。
基于以上,使用awk练习。
工作流分为大致三部分, read->excute->repeat,实现对文本的处理。
程序机构
BEGIN 语法:
BEGIN {awk-commands}
是可以省略的部分块,主要作用是声明变量,初始化变量,BODY块 :
{commonds}
,是必须填写的部分,主要作用是处理文本,会对输入的每一行都执行body块中的命令,并且body是没有关键字的。
-END :END {commands}
,同BEGIN,是可以省略的部分
基础语法
awk命令行,可以通过执行
awk [-option] files
来实现对files文件的处理。 如awk {print} mark.txt
这里就不具体举例了,开头的链接里讲的非常详细,这里只做简单的记录和查看。使用命令文件方式
awk -f command.awk marks.txt
使用-f参数,可以使用文件中的命令。awk基本选项 : 这里不具体总结,linux环境下终端
man awk
可以看到非常多的选项。
基本使用示例
基本打印文件内容
1
2
3
4
5
6$ awk '{print}' mark.txt
1) Amit Physics 80
2) Rahul Maths 90
3) Shyam Biology 87
4) Kedar English 85
5) Hari History 89打印具体项内容
1
2
3
4
5
6$ awk '{print $1 "\t" $2 }' mark.txt
1) Amit
2) Rahul
3) Shyam
4) Kedar
5) Hari添加限定条件的打印内容
1
2
3
4
5$ awk '/a/ {print $1 "\t" $2 }' mark.txt
2) Rahul
3) Shyam
4) Kedar
5) Hari结果只显示匹配到a的行
打印匹配到的行数
1
2$ awk 'BEGIN{count=0} /a/ { count++} END{print count}' mark.txt
4打印字符数量超过16的行
1
2
3$ awk 'length($0) > 18' marks.txt
3) Shyam Biology 87
4) Kedar English 85
NOTE:在这里的参数和bash中的参数类似。$0当前行,$1之后表示对应文件的行的列。
内建变量
AWK提供了很多内建变量提供使用,能够起到很大的作用。
标准awk变量
ARGC 命令行参数个数
1
2$ awk 'BEGIN{print "argument=",ARGC}' one two three
argument= 4ARGV 命令行参数数组 如
ARGV[1]=...
CONVFMT 数字的约定格式,默认值是%.6g
ENVIRON 环境变量
1
2$ awk 'BEGIN {print "User is",ENVIRON["USER"]}'
User is nanyinFILENAME 当前文件的名称
1
2$ awk 'END{print "this file name is", FILENAME}' mark.txt
this file name is mark.txtFS 分割符 默认是空格也可以使用-F设置分割符
NF 当前行的字段数目
1
2$ awk 'END{print NF}' mark.txt
4NR 行号
FNR 当前文件的行号
OFS 输出字段分隔符
ORS 输出行分割符
RLENGTH 表示match函数匹配字符床的长度
1
2$ awk 'BEGIN {if(match("One Three","ree")) {print RLENGTH}}'
3RSTART 表示match函数第一次匹配到的位置
1
2$ awk 'BEGIN {if(match("One Three","ree")) {print RSTART}}'
8
操作符
与C语言的操作符基本相同,如数字的一元二元三元操作等,字符串的链接,数组元素等
正则表达式
AWK对正则的处理非常强大,通常你一个小小的正则表达式能够处理很复杂的问题。关于正则,有时间整理一篇专门关于正则的文章。
数组
AWK支持关联数组,也就是说,不仅可以使用数字索引的数组,还可以使用字符串作为索引。删除数组元素使用delete语句
流程控制
流程控制if while for 与C相同
函数
查手册吧。。一次性看不完。。。。内建函数手册,这里有在这章比较重要的字符串函数。接下来就来看看有哪些函数比较重要。
AWK对字符串操作的函数
整理出awk对字符串的几个具体函数操作。
asort(source,dest,how)
asorti(source,dest,how)
以上两个函数的how先不解释,前两个参数分别为source数组和排序方式,第二个可以不写,默认使用第一位的进行排位。
1
2
3
4awk 'BEGIN{a[0]="xiaohong";a[1]="aiaolan";asort(a);for(i=2;i>=0;i--) {print a[i]}}'
xiaohong
aiaolan
`asorti()函数会将顺序替换到数组的value处如:
1
2
3awk 'BEGIN{a[0]="xiaohong";a[1]="aiaolan";asorti(a);for(i=2;i>=0;i--) {print a[i]}}'
1
0gensub(regexp,replacement,how[,target]) 类似gsub和sub
替换匹配到的正则regexp为replacement.如果how是g或者G(global的简写),则表示替换所有使用regexp匹配到的字符串,target是目标字符串
如果使用regexp未匹配到,则返回原始target的值
1
2
3
4
5
6
7
8
9
10
11# 第一个
echo a b c a d | gawk '{print gensub(/a/,"AA",2)}'
a b c AA d
# 第二个
awk '
BEGIN{
a="abc def"
b = gensub(/(.+) (.+)/,"\\2 \\1","g",a)
print b
}'
def abc
gsub(regexp,replacement[,target])
gsub中的‘g’其实是表示的是global,寻找目标的匹配到从左最长的,不重叠的,找到并且替换掉。
1
{ gsub(/Britain/, "United Kingdom"); print }
返回的值为匹配到的次数
index(in,find)
寻找in串内符合find匹配到的字符的index位置
1
2
3$ awk 'BEGIN{
quote> print index("hello","lo")}'
4length([string]) 顾名思义,不解释了
1
2$ awk 'BEGIN{print length("hello")}'
5NOTE: If no argument is supplied, length() returns the length of $0.
match(string,regexp,[,array])
使用正则匹配字符串,返回匹配到的位置,若未匹配到返回0
split(string,array[,fieldsep[,seps]])
分割string字符串,使用array存放分割后产生的字符组,使用fieldsep组为分割符,seps存放每次分割产生的分割符。一个分割出来的存放到array[1]中,第二个存放到array[2]中,以此类推。如果分割符fieldsep不写,则默认分割符为空格。
1
2
3
4
5$ awk 'BEGIN{print split("cul-de-sac",a,"-",seps);for(i=1;i<4;i++){print a[i]}}'
3
cul
de
sacsprintf(format,expression1,..)
是printf的功能,并且能够返回字符串
strtonum (str)
类似java的parseInt()函数,由String字符串转成数字
sub(regexp,replacement[,target])
最左最长匹配原则进行匹配,sub个gsub的作用相同,分割字符串,并进行替换
substr(string,start[,end])
分割字符串
tolower(string) & toupper(string)
大小写转换
关于awk的就总结到这了。。十分基础的总结。。推荐文档,清晰明了。下一篇打算先整理整理正则表达式。现在哪里都会用到正则,还是很有必要看看正则的。